﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;

/**
 * Our base Environment.
 * Exists solely so that all other Environments
 * can inherit from this.
 */
public class EnvBase
{
    // Member vars here
    protected EnvStack m_parentStack;

    /**
     * Constructor goes here.
     */
    public EnvBase()
    {
        m_parentStack = Game.getGame().getEnvStack();
    }

    /**
     * Saves level information to a binary file.
     * @param list - SpawnPoint list that we are to save.
     * @param filename - Name of the file to save information to, without path information.
     */
    public static void SaveSpawnList(List<SpawnPoint> list, Levels.List level)
    {
        /**
         * Contains all necessary logic for saving out spawn lists
         */
        try
        {
            FileStream fOut = new FileStream(@"Content\levels\" + Levels.s_names[(int)level],
                FileMode.Create, FileAccess.Write, FileShare.ReadWrite);

            BinaryWriter bw = new BinaryWriter(fOut);
            Vector3 position;
            Vector2 topLeft;
            Vector2 bottomRight;
            bool isActive;
            short type;

            // Number of SpawnPoints in our list
            bw.Write((Int32)list.Count);
            for (int i = 0; i < list.Count; i++)
            {
                position = list[i].getPosition();
                topLeft = list[i].getTopLeft();
                bottomRight = list[i].getBottomRight();
                isActive = list[i].isActive();
                type = (short)list[i].getType();

                bw.Write(position.X);
                bw.Write(position.Y);
                bw.Write(position.Z);

                bw.Write(topLeft.X);
                bw.Write(topLeft.Y);

                bw.Write(bottomRight.X);
                bw.Write(bottomRight.Y);

                bw.Write(isActive);

                bw.Write(type);
            }
            bw.Close();
        }

        catch (IOException e)
        {
            // TODO: Catch this
        }
    }

    /**
     * Loads level information from a binary file into a SpawnPoint list.
     * @param filename - Name of the file to load, without path information.
     */
    public static List<SpawnPoint> LoadSpawnList(Levels.List level)
    {
        /**
         * Reverses SaveSpawnList, loading our list from file
         */
        List<SpawnPoint> list = new List<SpawnPoint>();
        try
        {
            FileStream fIn = new FileStream(@"Content\levels\" + Levels.s_names[(int)level],
                FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

            BinaryReader br = new BinaryReader(fIn);
            br.BaseStream.Seek(0, SeekOrigin.Begin);
            int count;
            Vector3 position = new Vector3();
            Vector2 topLeft = new Vector2();
            Vector2 bottomRight = new Vector2();
            bool isActive;
            short type;

            // Number of SpawnPoints in our list
            count = br.ReadInt32();
            for (int i = 0; i < count; i++)
            {
                position.X = br.ReadSingle();
                position.Y = br.ReadSingle();
                position.Z = br.ReadSingle();

                topLeft.X = br.ReadSingle();
                topLeft.Y = br.ReadSingle();

                bottomRight.X = br.ReadSingle();
                bottomRight.Y = br.ReadSingle();

                isActive = br.ReadBoolean();

                type = br.ReadInt16();

                list.Add(new SpawnPoint(position, topLeft, bottomRight, isActive, (ObjectFactory.TypeEnum)type));
            }
            br.Close();
        }

        catch (IOException e)
        {
            // TODO: Catch this
        }
        return list;
    }

    /**
     * Abstract update function.
     * To be implemented by all children.
     * @param dt
     */
    virtual public void update(double dt) { }

    /**
     * Abstract render function.
     * To be implemented by all children.
     */
    virtual public void render() { }
}
